<!--
 * Copyright © 2022
 * @Author: zhangxiang
 * @Date: 2022-11-21 17:13:52
 * @LastEditors: zhangxiang
 * @LastEditTime: 2023-08-11 14:19:59
 * @Description:
 *
-->

<template>
  <MyContainer class="container">
    <MyHeader class="header">
      <el-input
        v-model="searchKey"
        style="width: 200px; margin-right: 20px"
        size="medium"
        class="input"
        placeholder="请输入关键字进行过滤"
        clearable
        @clear="clearClick"
        @keyup.enter.native="queryClick"
      />
      <el-button
        size="medium"
        type="primary"
        @click="queryClick"
      >查询</el-button>
      <el-button size="medium" @click="resetClick">重置</el-button>
      <el-button
        size="medium"
        style="margin-left: auto"
        type="primary"
        icon="el-icon-refresh"
        :loading="btnLoadingSync"
        @click="syncClick"
      >同步</el-button>
      <el-button
        size="medium"
        type="primary"
        icon="el-icon-plus"
        @click="createClick"
      >创建云主机</el-button>
    </MyHeader>
    <div class="main">
      <div v-for="(item, index) in list" :key="index" class="list-item">
        <el-row class="top" type="flex" align="middle">
          <div class="name">{{ item.vmName }}</div>
          <el-tag
            :type="
              item.runStatus === '关机'
                ? 'danger'
                : item.runStatus === '未就绪'
                  ? 'warning'
                  : 'success'
            "
            size="small"
            style="margin-left: 15px"
          >{{ item.runStatus }}</el-tag>
          <el-button
            type="primary"
            size="mini"
            style="margin-left: auto; height: 22px; padding: 0 10px"
            :loading="item.remoteVMLoading"
            @click="remoteVMClick(item, index)"
          >远程连接</el-button>
          <el-button
            type="success"
            size="mini"
            style="height: 22px; padding: 0 10px"
            :loading="item.startVMLoading"
            :disabled="item.runStatus != '关机'"
            @click="startVMClick(item, index)"
          >开机</el-button>
          <el-button
            type="warning"
            style="height: 22px; padding: 0 10px"
            size="mini"
            :loading="item.stopVMLoading"
            :disabled="
              !(item.runStatus == '运行中' || item.runStatus == '未就绪')
            "
            @click="stopVMClick(item, index)"
          >关机</el-button>
          <el-button
            type="primary"
            size="mini"
            style="height: 22px; padding: 0 10px"
            @click="editClick(item)"
          >编辑</el-button>
          <el-button
            type="danger"
            style="height: 22px; padding: 0 10px"
            size="mini"
            :loading="item.deleteBtnLoading"
            @click="deleteClick(item, index)"
          >删除</el-button>
        </el-row>
        <div class="divider"></div>
        <div class="block">
          <div class="title">基本信息</div>
          <div class="row">
            <div class="row-item">
              <div class="key">虚拟机ID</div>
              <div class="val">{{ item.id }}</div>
            </div>
            <div class="row-item">
              <div class="key">云服务商</div>
              <div class="val">{{ item.cloudProvider }}</div>
            </div>
            <div class="row-item">
              <div class="key">云账号名称</div>
              <div class="val">{{ item.cloudAccountName }}</div>
            </div>
            <div class="row-item">
              <div class="key">可用区</div>
              <div class="val">{{ item.zone || "-" }}</div>
            </div>
            <div class="row-item">
              <div class="key">计费模式</div>
              <div class="val">{{ item.chargeType || "-" }}</div>
            </div>
            <div class="row-item"></div>
          </div>
        </div>
        <div class="block">
          <div class="title">网络信息</div>
          <div class="row">
            <div class="row-item">
              <div class="key">VPC ID</div>
              <div class="val">{{ item.vpcId }}</div>
            </div>
            <div class="row-item">
              <div class="key">子网ID</div>
              <div class="val">{{ item.subnetId }}</div>
            </div>
            <div class="row-item">
              <div class="key">安全组ID</div>
              <div class="val">{{ item.nsgId }}</div>
            </div>
            <div class="row-item">
              <div class="key">公网IP</div>
              <div class="val">{{ item.publicIp }}</div>
            </div>
            <div class="row-item">
              <div class="key">私网IP</div>
              <div class="val">{{ item.privateIp }}</div>
            </div>
            <div class="row-item"></div>
          </div>
        </div>
        <div class="block">
          <div class="title">规格镜像</div>
          <div class="row instanceType">
            <div class="row-item">
              <div class="key">CPU(Cores)</div>
              <div class="val">{{ item.cpuCount }}</div>
            </div>
            <div class="row-item">
              <div class="key">内存(GiB)</div>
              <div class="val">{{ item.memSize }}</div>
            </div>
            <div class="row-item">
              <div class="key">硬盘(GiB)</div>
              <div class="val">{{ item.diskSize }}</div>
            </div>
            <div class="row-item">
              <div class="key">GPU</div>
              <div class="val">{{ item.gpu || "-" }}</div>
            </div>
            <div class="row-item">
              <div class="key">GPU显存</div>
              <div class="val">{{ item.gpuMemSize || "-" }}</div>
            </div>
            <div class="row-item">
              <div class="key">镜像</div>
              <div class="val">{{ item.image }}</div>
            </div>
            <div class="row-item">
              <div class="key">操作系统</div>
              <div class="val">{{ item.os }}</div>
            </div>
          </div>
        </div>
        <div class="block">
          <div class="title">其他信息</div>
          <div class="row">
            <div class="row-item">
              <div class="key">标签</div>
              <div class="val">{{ getLabelText(item.vmTags) }}</div>
            </div>
            <div class="row-item">
              <div class="key">登录密码</div>
              <div class="val">{{ item.pwd || "-" }}</div>
            </div>
            <div class="row-item">
              <div class="key">是否被K8s纳管</div>
              <div class="val">{{ item.k8sManaged }}</div>
            </div>
            <div class="row-item">
              <div class="key">创建人</div>
              <div class="val">{{ item.createBy }}</div>
            </div>
            <div class="row-item">
              <div class="key">创建时间</div>
              <div class="val">{{ item.createDate }}</div>
            </div>
            <div class="row-item"></div>
          </div>
          <div class="row last">
            <div class="row-item">
              <div class="key">描述</div>
              <div class="val">{{ item.desc }}</div>
            </div>
          </div>
        </div>
      </div>
      <el-row type="flex" justify="end" style="margin-top: 30px">
        <el-pagination
          background
          layout="total, sizes, prev, pager, next"
          :page-sizes="[5, 10, 20, 30]"
          :page-size="pageSize"
          :current-page.sync="pageNum"
          :total="totalCount"
          @current-change="changePage"
          @size-change="sizeChange"
        />
      </el-row>
    </div>

    <CreateDialog
      v-if="showCreateDialog"
      :show.sync="showCreateDialog"
      @success="createSuccessCallback"
    />

    <UpdateDialog
      v-if="showUpdateDialog"
      :show.sync="showUpdateDialog"
      :info="updateInfo"
      @success="updateSuccessCallback"
    />
  </MyContainer>
</template>

<script>
import pagePermissionMixin from '@/views/mixin/pagePermission.js'
import pageQueryMixin from '@/views/mixin/pageQuery.js'
import MyContainer from '@/components/Layout/MyContainer.vue'
import MyHeader from '@/components/Layout/MyHeader.vue'
import {
  getVMList,
  deleteVM,
  syncVM,
  startVM,
  stopVM,
  vncRemoteVM,
  createSnapshotVM
} from '@/api/cn-resource'
import CreateDialog from './components/CreateDialog.vue'
import UpdateDialog from './components/UpdateDialog.vue'

export default {
  name: 'VMMgmt',
  components: {
    MyContainer,
    MyHeader,
    CreateDialog,
    UpdateDialog
  },
  mixins: [pagePermissionMixin, pageQueryMixin],
  data() {
    return {
      selection: [],
      btnLoadingSync: false,
      btnLoadingBatchDel: false,
      btnLoadingBatchStart: false,
      btnLoadingBatchStop: false,
      showCreateDialog: false,
      showUpdateDialog: false,
      updateInfo: {}
    }
  },
  created() {},
  methods: {
    /**
     * @description: 更新成功
     * @return {*}
     */
    updateSuccessCallback() {
      this.$message.success({
        message: '编辑云主机成功',
        duration: 2000
      })
      this.searchKey = ''
      this.getList() // 请求数据
    },
    /**
     * @description: 创建成功
     * @return {*}
     */
    createSuccessCallback() {
      this.$message.success({
        message: '创建云主机成功',
        duration: 2000
      })
      this.searchKey = ''
      this.pageNum = 1
      this.getList() // 请求数据
    },
    /**
     * @description: 获取标签
     * @param {*} vmTags
     * @return {*}
     */
    getLabelText(vmTags) {
      // 标签数组转为字符
      let text = ''
      if (Array.isArray(vmTags)) {
        text = vmTags.reduce((prev, cur, index) => {
          // 通过reduce拼接
          return prev + (index === 0 ? '' : ' / ') + cur.key + ':' + cur.value
        }, '')
      }
      return text
    },
    handleSelectionChange(selection) {
      this.selection = selection
    },
    /**
     * @description: 关机
     * @param {*} item
     * @param {*} index
     * @return {*}
     */
    stopVMClick(item, index) {
      this.$set(this.list[index], 'stopVMLoading', true)
      stopVM({
        ids: [item.id]
      })
        .then((res) => {
          this.$message.success({
            message: '关机成功！',
            duration: '2000'
          })
          this.getList() // 请求数据
        })
        .finally(() => {
          this.list[index].stopVMLoading = false
        })
    },
    /**
     * @description: 开机
     * @param {*} item
     * @param {*} index
     * @return {*}
     */
    startVMClick(item, index) {
      this.$set(this.list[index], 'startVMLoading', true)
      startVM({
        ids: [item.id]
      })
        .then((res) => {
          this.$message.success({
            message: '开机成功！',
            duration: '2000'
          })
          this.getList() // 请求数据
        })
        .finally(() => {
          this.list[index].startVMLoading = false
        })
    },
    /**
     * @description: 远程连接
     * @param {*} item
     * @return {*}
     */
    remoteVMClick(item, index) {
      this.$set(this.list[index], 'remoteVMLoading', true)
      vncRemoteVM({
        id: item.id
      })
        .then((res) => {
          if (res.data && res.data.url) {
            window.open(res.data.url)
          } else {
            this.$message.warning({
              message: '远程连接出错 请稍候再试',
              duration: '2000'
            })
          }
        })
        .finally(() => {
          this.list[index].remoteVMLoading = false
        })
    },
    /**
     * @description: 创建快照
     * @param {*} row
     * @return {*}
     */
    createSnapshot(row) {
      createSnapshotVM({
        id: row.id
      }).then((res) => {
        this.$message.success({
          message: '创建快照成功！',
          duration: '2000'
        })
      })
    },
    /**
     * @description: 开机
     * @param {*} params
     * @return {*}
     */
    startVMs(params) {
      startVM(params)
        .then((res) => {
          this.$message.success({
            message: '开机成功！',
            duration: '2000'
          })
          this.getList() // 请求数据
        })
        .finally(() => {
          this.btnLoadingBatchStart = false
        })
    },
    /**
     * @description: 关机
     * @param {*} params
     * @return {*}
     */
    stopVMs(params) {
      stopVM(params)
        .then((res) => {
          this.$message.success({
            message: '关机成功！',
            duration: '2000'
          })
          this.getList() // 请求数据
        })
        .finally(() => {
          this.btnLoadingBatchStop = false
        })
    },

    /**
     * @description: 编辑
     * @return {*}
     */
    editClick(row) {
      this.updateInfo = row
      this.showUpdateDialog = true
    },
    /**
     * @description: 关机
     * @return {*}
     */
    stopBatchClick() {
      if (this.selection.length === 0) {
        this.$message.warning('请先选择云主机')
        return
      }
      const ids = []
      for (const item of this.selection) {
        ids.push(item.id)
      }
      this.btnLoadingBatchStop = true
      this.stopVMs({ ids: ids })
    },
    /**
     * @description: 开机
     * @return {*}
     */
    startBatchClick() {
      if (this.selection.length === 0) {
        this.$message.warning('请先选择云主机')
        return
      }
      const ids = []
      for (const item of this.selection) {
        ids.push(item.id)
      }
      this.btnLoadingBatchStart = true
      this.startVMs({ ids: ids })
    },
    /**
     * @description: 批量删除
     * @return {*}
     */
    batchDeleteClick() {
      if (this.selection.length === 0) {
        this.$message.warning('请先选择云主机')
        return
      }
      const ids = []
      for (const item of this.selection) {
        ids.push(item.id)
      }
      this.$confirm(
        '若删除当前选择云主机则相应业务也会全部停止并删除',
        '提示',
        {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          closeOnClickModal: false,
          type: 'warning'
        }
      ).then(() => {
        this.btnLoadingBatchDel = true
        this.deleteVMs({
          ids: ids
        })
      })
    },
    /**
     * @description: 创建
     * @return {*}
     */
    createClick() {
      this.showCreateDialog = true
    },
    /**
     * @description: 同步
     * @return {*}
     */
    syncClick() {
      this.btnLoadingSync = true
      syncVM({})
        .then((res) => {
          this.$message.success({
            message: '同步成功！',
            duration: '2000'
          })
          this.pageNum = 1
          this.getList() // 请求数据
        })
        .finally(() => {
          this.btnLoadingSync = false
        })
    },
    /**
     * @description: 删除
     * @param {*} params
     * @return {*}
     */
    deleteVMs(params) {
      deleteVM(params)
        .then((res) => {
          this.$message.success('删除成功')
          if (this.list.length === 1) {
            // 当前页只有一条数据时 删除完刷新上一页数据
            this.pageNum = Math.max(this.pageNum - 1, 1)
          }
          this.getList() // 请求数据
        })
        .finally(() => {
          this.btnLoadingBatchDel = false
        })
    },
    /**
     * @description: 删除
     * @param {*} row
     * @param {*} index
     * @return {*}
     */
    deleteClick(row, index) {
      this.$confirm('若删除当前云主机则相应业务也会全部停止并删除', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        closeOnClickModal: false,
        type: 'warning'
      }).then(() => {
        this.$set(this.list[index], 'deleteBtnLoading', true)
        deleteVM({
          ids: [row.id]
        })
          .then((res) => {
            this.$message.success('删除成功')
            if (this.list.length === 1) {
              // 当前页只有一条数据时 删除完刷新上一页数据
              this.pageNum = Math.max(this.pageNum - 1, 1)
            }
            this.getList() // 请求数据
          })
          .finally(() => {
            this.list[index].deleteBtnLoading = false
          })
      })
    },
    /**
     * @description: 获取列表
     * @return {*}
     */
    getList() {
      this.handleRequestAndResp(getVMList, {
        keyword: this.searchKey,
        pageNum: this.pageNum,
        pageSize: this.pageSize
      })
    }
  }
}
</script>

<style lang="less" scoped>
@import "@/assets/css/common.less";
.container {
  .list-item {
    background: #ffffff;
    box-shadow: 0px 0px 5px 0px rgba(217, 213, 234, 0.5);
    border-radius: 4px;
    padding: 15px 20px;
    margin-bottom: 20px;

    .top {
      margin-bottom: 10px;
    }

    .name {
      .textStyle(16px, 600, #262626);
      line-height: 24px;
    }

    .divider {
      margin-bottom: 10px;
      height: 1px;
      background: #f2f2f2;
    }

    .block {
      margin-bottom: 10px;
      background: #ffffff;
      border-radius: 1px;
      border: 1px solid #ececec;
      &:last-child {
        margin-bottom: 0;
      }

      .title {
        background: #fdfdfd;
        border-bottom: 1px solid #ececec;
        height: 30px;
        line-height: 30px;
        .textStyle(14px, 500, #262626);
        padding-left: 20px;
      }

      .row {
        display: flex;
        align-items: center;
        padding: 9px 20px;
        &.last {
          padding-top: 0;
        }

        .row-item {
          flex: 1;
          .key {
            display: inline-block;
            margin-right: 12px;
            .textStyle(14px, 400, #C3C3C3);
            line-height: 20px;
          }
          .val {
            display: inline-block;
            .textStyle(14px, 500, #4a4a4a);
            line-height: 20px;
          }
        }
        &.instanceType {
          justify-content: space-between;
          .row-item {
            flex: unset;
          }
        }
      }
    }
  }
  .detail-dialog {
    /deep/ .el-dialog {
      min-width: 600px;
    }
    /deep/ .detailLabel {
      .textStyle(15px , 400, #606266);
    }
    /deep/ .detailContent {
      .textStyle(15px , 500, #606266);
    }
  }
}
</style>
